(module translator
  (lib "eopl.ss" "eopl")                ; use the eopl language level
  
  (require "lang.scm")
  (provide translation-of-program)
  
  
  ;;;;;;;;;;;;;;;; lexical address calculator ;;;;;;;;;;;;;;;;
  
  (define translation-of-program
    (lambda (pgm)
      (cases program pgm
	(a-program (body)
	  (a-program
	    (translation-of body (init-senv)))))))
  
  (define translation-of
    (lambda (exp senv)
      (cases expression exp

	(const-exp (num) exp)
             
	(diff-exp (e1 e2)
	  (diff-exp
	    (translation-of e1 senv)
	    (translation-of e2 senv)))

	(var-exp (id)
	  (lexref-exp
	    (apply-senv senv id)))

	(let-exp (bvar rhs body)
	  (nameless-let-exp
	    (translation-of rhs senv)            
	    (translation-of body
	      (extend-senv bvar senv))))

	(proc-exp (bvar body)
	  (nameless-proc-exp
	    (translation-of body
	      (extend-senv bvar senv))))
        (zero?-exp (exp)
                   (zero?-exp
                    (translation-of exp senv)
                    )
                   )
        
        (if-exp (e1 e2 e3)
                (if-exp
                 (translation-of e1 senv)
                 (translation-of e2 senv)
                 (translation-of e3 senv)
                 )
                )
        (app-exp (rator rand)
                 (app-exp
                  (translation-of rator senv)
                  (translation-of rand senv)
                  )
                 )

        ;; ... you need to fill in the other cases ...

	(else (eopl:error 'translation-of
		"Illegal source expression ~s" exp))
	)))
  
   ;;;;;;;;;;;;;;;; static environments ;;;;;;;;;;;;;;;;
  
  ;;; senv = (list symbol)
  
  (define init-senv
    (lambda ()
      '(i v x)))
  
  (define extend-senv
    (lambda (bvar senv)
      (cons bvar senv)))
  
  (define apply-senv
    (lambda (senv bvar)
      (cond
	((null? senv) 
	 (eopl:error 'translation-of "unbound variable in code: ~s" bvar))
	((eqv? bvar (car senv))
	 0)
	(else
	  (+ 1 (apply-senv (cdr senv) bvar))))))
  
  )